package com.magupe.push.server;

import com.magupe.push.common.codec.PacketDecoder;
import com.magupe.push.common.codec.PacketEncoder;
import com.magupe.push.common.codec.Spliter;
import com.magupe.push.server.handler.AuthenticationRequestHandler;
import com.magupe.push.server.handler.FileRequestHandler;
import com.magupe.push.server.handler.LoginRequestHandler;
import com.magupe.push.server.handler.MessageRequestHandler;
import com.magupe.push.server.handler.RPCMessageRequestHandler;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * https://www.cnblogs.com/ruixueyan/p/6382770.html
 */
public class NettyPushServer {

	private static final int PORT = 7000;
	
	public static void main(String[] args) throws InterruptedException {
		int port = PORT;
		if(args != null && args.length > 0) {
			port = Integer.parseInt(args[0]);
		}
		
		NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        
        try {
            final ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap
            	.group(bossGroup, workerGroup)
            	.channel(NioServerSocketChannel.class)
            	.option(ChannelOption.SO_BACKLOG, 1024)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
    				@Override
    				protected void initChannel(NioSocketChannel ch) throws Exception {
    					ch.pipeline().addLast(new Spliter());
    					ch.pipeline().addLast(new PacketDecoder());
    					ch.pipeline().addLast(new LoginRequestHandler());
    					ch.pipeline().addLast(new AuthenticationRequestHandler());
    					ch.pipeline().addLast(new MessageRequestHandler());
    					ch.pipeline().addLast(new RPCMessageRequestHandler());
    					ch.pipeline().addLast(new FileRequestHandler());
    					ch.pipeline().addLast(new PacketEncoder());
    				}
                });
            
            // Bind and start to accept incoming connections.
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); 
            
            // Wait until the server socket is closed.
            // In this example, this does not happen, but you can do that to gracefully
            // shut down your server.            
            channelFuture.channel().closeFuture().sync();
		} finally {
			// 释放线程池资源
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}
}
